package com.imgrate.migration.service;

import com.imgrate.migration.entity.Server;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SshService {

    // 连接超时时间（毫秒）
    private static final int CONNECTION_TIMEOUT = 15000;
    // 通道超时时间（毫秒）
    private static final int CHANNEL_TIMEOUT = 10000;
    // 最大重试次数
    private static final int MAX_RETRIES = 3;
    // 重试间隔（毫秒）
    private static final int RETRY_INTERVAL = 2000;

    /**
     * 测试服务器连接
     * @param server 服务器信息
     * @return 连接测试结果
     */
    public ConnectionResult testConnection(Server server) {
        ConnectionResult result = new ConnectionResult();
        result.setServerId(server.getId());
        result.setServerName(server.getName());
        
        Session session = null;
        ChannelExec channel = null;
        
        try {
            log.info("[连接测试] 开始测试服务器连接: {}:{} (ID: {})", server.getHostname(), server.getPort(), server.getId());
            
            // 创建JSch实例
            JSch jsch = new JSch();
            
            // 如果提供了私钥，添加到JSch
            if (server.getPrivateKey() != null && !server.getPrivateKey().isEmpty()) {
                // 这里可以添加私钥认证逻辑
                // 暂时只实现密码认证
                log.debug("[连接测试] 使用私钥认证连接服务器 {}:{}", server.getHostname(), server.getPort());
            }
            
            // 创建会话
            session = jsch.getSession(server.getUsername(), server.getHostname(), server.getPort());
            
            // 设置密码
            if (server.getPassword() != null && !server.getPassword().isEmpty()) {
                session.setPassword(server.getPassword());
                log.debug("[连接测试] 使用密码认证连接服务器 {}:{}", server.getHostname(), server.getPort());
            }
            
            // 设置SSH配置
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no"); // 跳过主机密钥检查
            config.put("PreferredAuthentications", "password,keyboard-interactive,publickey");
            session.setConfig(config);
            
            // 连接
            log.info("[连接测试] 正在连接到服务器 {}:{}", server.getHostname(), server.getPort());
            session.connect(CONNECTION_TIMEOUT); // 使用配置的超时时间
            
            result.setSuccess(true);
            result.setMessage("连接成功");
            log.info("[连接测试] 成功连接到服务器 {}:{} (ID: {})", server.getHostname(), server.getPort(), server.getId());
            
            // 获取系统信息
            try {
                String systemInfo = executeCommand(session, "uname -a");
                result.setSystemInfo(systemInfo);
                log.debug("[系统信息] 服务器 {} 系统信息: {}", server.getHostname(), systemInfo);
            } catch (Exception e) {
                log.warn("[系统信息] 获取服务器 {} 系统信息失败: {}", server.getHostname(), e.getMessage());
                result.setSystemInfo("无法获取系统信息");
            }
            
        } catch (JSchException e) {
            log.error("[SSH错误] SSH连接服务器 {}:{} (ID: {}) 失败: {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
            result.setSuccess(false);
            result.setMessage("SSH连接失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("[连接测试] 连接测试服务器 {}:{} (ID: {}) 过程中发生错误: {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
            result.setSuccess(false);
            result.setMessage("连接测试失败: " + e.getMessage());
        } finally {
            // 关闭连接
            if (channel != null && channel.isConnected()) {
                channel.disconnect();
                log.debug("[连接关闭] 已断开与服务器 {}:{} (ID: {}) 的执行通道连接", server.getHostname(), server.getPort(), server.getId());
            }
            if (session != null && session.isConnected()) {
                session.disconnect();
                log.info("[连接关闭] 已断开与服务器 {}:{} (ID: {}) 的连接", server.getHostname(), server.getPort(), server.getId());
            }
        }
        
        return result;
    }
    
    /**
     * 在远程服务器上执行命令
     * @param server 服务器信息
     * @param command 要执行的命令
     * @return 命令执行结果
     */
    public CommandResult executeCommand(Server server, String command) {
        CommandResult result = new CommandResult();
        result.setServerId(server.getId());
        result.setServerName(server.getName());
        
        // 重试机制
        for (int attempt = 1; attempt <= MAX_RETRIES; attempt++) {
            Session session = null;
            ChannelExec channel = null;
            
            try {
                log.info("[命令执行] 尝试第 {}/{} 次执行命令 on {}:{} (ID: {}): {}", attempt, MAX_RETRIES, server.getHostname(), server.getPort(), server.getId(), command);
                
                // 创建JSch实例
                JSch jsch = new JSch();
                
                // 创建会话
                session = jsch.getSession(server.getUsername(), server.getHostname(), server.getPort());
                
                // 设置密码
                if (server.getPassword() != null && !server.getPassword().isEmpty()) {
                    session.setPassword(server.getPassword());
                } else if (server.getPrivateKey() != null && !server.getPrivateKey().isEmpty()) {
                    // 使用私钥认证
                    byte[] privateKeyBytes = server.getPrivateKey().getBytes(StandardCharsets.UTF_8);
                    jsch.addIdentity("privateKey", privateKeyBytes, null, null);
                    log.debug("[认证] 使用私钥认证连接服务器 {}:{}", server.getHostname(), server.getPort());
                }
                
                // 设置SSH配置
                Properties config = new Properties();
                config.put("StrictHostKeyChecking", "no"); // 跳过主机密钥检查
                config.put("PreferredAuthentications", "password,keyboard-interactive,publickey");
                config.put("ServerAliveInterval", "30"); // 保持连接
                config.put("ServerAliveCountMax", "3"); // 最大存活检查次数
                session.setConfig(config);
                
                // 连接
                session.connect(CONNECTION_TIMEOUT); // 使用配置的超时时间
                log.info("[连接成功] 成功连接到服务器 {}:{}", server.getHostname(), server.getPort());
                
                // 创建执行通道
                channel = (ChannelExec) session.openChannel("exec");
                channel.setCommand(command);
                
                // 创建输入流来读取命令输出
                InputStream in = channel.getInputStream();
                InputStream err = channel.getErrStream();
                
                // 连接通道
                channel.connect(CHANNEL_TIMEOUT); // 使用配置的超时时间
                log.info("[命令执行] 在服务器 {} 上成功执行命令", server.getHostname());
                
                // 读取输出
                StringBuilder output = new StringBuilder();
                StringBuilder errorOutput = new StringBuilder();
                byte[] tmp = new byte[1024];
                long startTime = System.currentTimeMillis();
                long timeout = 300000; // 5分钟超时
                
                while (true) {
                    // 检查是否超时
                    if (System.currentTimeMillis() - startTime > timeout) {
                        log.warn("[超时] 命令执行超时 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), command);
                        throw new RuntimeException("命令执行超时");
                    }
                    
                    while (in.available() > 0) {
                        int i = in.read(tmp, 0, 1024);
                        if (i < 0) break;
                        output.append(new String(tmp, 0, i));
                    }
                    while (err.available() > 0) {
                        int i = err.read(tmp, 0, 1024);
                        if (i < 0) break;
                        errorOutput.append(new String(tmp, 0, i));
                    }
                    if (channel.isClosed()) {
                        if (in.available() > 0) continue;
                        if (err.available() > 0) continue;
                        break;
                    }
                    try {
                        Thread.sleep(100);
                    } catch (Exception ee) {
                        // 忽略中断异常
                        log.debug("[中断] 命令执行线程被中断: {}", ee.getMessage());
                    }
                }
                
                // 设置结果
                result.setSuccess(channel.getExitStatus() == 0);
                result.setOutput(output.toString().trim());
                if (errorOutput.length() > 0) {
                    result.setMessage(errorOutput.toString().trim());
                    log.warn("[错误输出] 命令执行错误输出 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), errorOutput.toString().trim());
                }
                
                log.info("[执行完成] 服务器 {} 上命令执行完成，退出状态: {}", server.getHostname(), channel.getExitStatus());
                if (output.length() > 0) {
                    log.debug("[命令输出] 服务器 {} 上命令输出: {}", server.getHostname(), output.toString().trim());
                }
                
                return result; // 成功执行后直接返回
                
            } catch (JSchException e) {
                log.error("[SSH错误] SSH连接失败 (尝试 {}/{} on {}:{} (ID: {})): {}", attempt, MAX_RETRIES, server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                if (attempt == MAX_RETRIES) {
                    log.error("[SSH错误] SSH连接失败 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                    result.setSuccess(false);
                    result.setMessage("SSH连接失败: " + e.getMessage());
                }
            } catch (IOException e) {
                log.error("[IO错误] IO错误 (尝试 {}/{} on {}:{} (ID: {})): {}", attempt, MAX_RETRIES, server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                if (attempt == MAX_RETRIES) {
                    log.error("[IO错误] IO错误 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                    result.setSuccess(false);
                    result.setMessage("IO错误: " + e.getMessage());
                }
            } catch (Exception e) {
                log.error("[未知错误] 执行命令时发生未知错误 (尝试 {}/{} on {}:{} (ID: {})): {}", attempt, MAX_RETRIES, server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                if (attempt == MAX_RETRIES) {
                    log.error("[执行失败] 执行命令时发生错误 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                    result.setSuccess(false);
                    result.setMessage("执行命令时发生错误: " + e.getMessage());
                }
            } finally {
                // 正确关闭channel
                if (channel != null) {
                    try {
                        channel.disconnect();
                        log.debug("[通道关闭] 已断开与服务器 {}:{} (ID: {}) 的执行通道连接", server.getHostname(), server.getPort(), server.getId());
                    } catch (Exception e) {
                        log.warn("[关闭警告] 关闭SSH通道时出错 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage());
                    }
                }
                if (session != null && session.isConnected()) {
                    try {
                        session.disconnect();
                        log.info("[会话关闭] 已断开与服务器 {}:{} (ID: {}) 的连接", server.getHostname(), server.getPort(), server.getId());
                    } catch (Exception e) {
                        log.warn("[关闭警告] 关闭SSH会话时出错 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage());
                    }
                }
            }
            
            // 如果不是最后一次尝试，等待一段时间再重试
            if (attempt < MAX_RETRIES) {
                try {
                    log.info("[重试等待] 等待 {} 毫秒后进行第 {} 次重试 on {}:{} (ID: {})", RETRY_INTERVAL, attempt + 1, server.getHostname(), server.getPort(), server.getId());
                    Thread.sleep(RETRY_INTERVAL);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    log.warn("[中断] 重试等待被中断: {}", ie.getMessage());
                    break;
                }
            }
        }
        
        return result;
    }
    
    /**
     * 在已连接的会话中执行命令
     * @param session SSH会话
     * @param command 要执行的命令
     * @return 命令执行结果
     * @throws Exception 执行异常
     */
    private String executeCommand(Session session, String command) throws Exception {
        ChannelExec channel = null;
        StringBuilder result = new StringBuilder();
        
        try {
            log.debug("[内部执行] 在已连接会话中执行命令: {}", command);
            channel = (ChannelExec) session.openChannel("exec");
            channel.setCommand(command);
            
            // 获取输入流和错误流
            BufferedReader reader = new BufferedReader(new InputStreamReader(channel.getInputStream()));
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(channel.getErrStream()));
            
            // 连接通道
            channel.connect(CHANNEL_TIMEOUT);
            
            // 读取标准输出
            String line;
            while ((line = reader.readLine()) != null) {
                result.append(line).append("\n");
            }
            
            // 读取错误输出
            StringBuilder errorResult = new StringBuilder();
            while ((line = errorReader.readLine()) != null) {
                errorResult.append(line).append("\n");
            }
            
            // 如果有错误输出，记录到日志
            if (errorResult.length() > 0) {
                log.warn("[内部错误] 命令执行错误输出: {}", errorResult.toString().trim());
            }
            
        } finally {
            // 正确关闭channel
            if (channel != null) {
                try {
                    channel.disconnect();
                    log.debug("[内部关闭] 已断开执行通道连接");
                } catch (Exception e) {
                    log.warn("[内部警告] 关闭SSH通道时出错: {}", e.getMessage());
                }
            }
        }
        
        return result.toString().trim();
    }
    
    /**
     * 通过SCP将本地文件传输到远程服务器
     * @param server 服务器信息
     * @param localFilePath 本地文件路径
     * @param remoteFilePath 远程文件路径
     * @return 传输结果
     */
    public CommandResult transferFileToServer(Server server, String localFilePath, String remoteFilePath) {
        CommandResult result = new CommandResult();
        result.setServerId(server.getId());
        result.setServerName(server.getName());
        
        // 检查本地文件是否存在
        File localFile = new File(localFilePath);
        if (!localFile.exists()) {
            log.error("[文件错误] 本地文件不存在: {} (服务器: {}:{} (ID: {}))", localFilePath, server.getHostname(), server.getPort(), server.getId());
            result.setSuccess(false);
            result.setMessage("本地文件不存在: " + localFilePath);
            return result;
        }
        
        log.info("[文件传输] 开始传输文件 {} 到服务器 {}:{} (ID: {}) 路径: {}", localFilePath, server.getHostname(), server.getPort(), server.getId(), remoteFilePath);
        log.debug("[文件信息] 本地文件大小: {} 字节", localFile.length());
        
        // 重试机制
        for (int attempt = 1; attempt <= MAX_RETRIES; attempt++) {
            Session session = null;
            ChannelSftp channel = null;
            
            try {
                log.info("[传输尝试] 尝试第 {}/{} 次传输文件 {} 到 {}:{}", attempt, MAX_RETRIES, localFilePath, server.getHostname(), remoteFilePath);
                
                // 创建JSch实例
                JSch jsch = new JSch();
                
                // 创建会话
                session = jsch.getSession(server.getUsername(), server.getHostname(), server.getPort());
                
                // 设置密码
                if (server.getPassword() != null && !server.getPassword().isEmpty()) {
                    session.setPassword(server.getPassword());
                }
                
                // 设置SSH配置
                Properties config = new Properties();
                config.put("StrictHostKeyChecking", "no"); // 跳过主机密钥检查
                config.put("PreferredAuthentications", "password,keyboard-interactive,publickey");
                config.put("ServerAliveInterval", "60"); // 保持连接
                config.put("ServerAliveCountMax", "3"); // 最大存活检查次数
                session.setConfig(config);
                
                // 连接
                log.info("[连接建立] 正在连接到服务器 {}:{}", server.getHostname(), server.getPort());
                session.connect(CONNECTION_TIMEOUT); // 使用配置的超时时间
                
                // 创建SFTP通道
                channel = (ChannelSftp) session.openChannel("sftp");
                channel.connect(CHANNEL_TIMEOUT); // 使用配置的超时时间
                
                // 确保远程目录存在
                String remoteDir = remoteFilePath.substring(0, remoteFilePath.lastIndexOf("/"));
                if (!remoteDir.isEmpty() && !remoteDir.equals("/")) {
                    try {
                        channel.mkdir(remoteDir);
                        log.info("[目录创建] 创建远程目录: {}", remoteDir);
                    } catch (SftpException e) {
                        // 目录可能已存在，忽略错误
                        log.debug("[目录检查] 远程目录创建可能失败（可能已存在）: {}", remoteDir);
                    }
                }
                
                // 传输文件
                log.info("[传输开始] 开始传输文件 {} 到 {}:{}", localFilePath, server.getHostname(), remoteFilePath);
                channel.put(localFilePath, remoteFilePath);
                
                result.setSuccess(true);
                result.setMessage("文件传输成功");
                log.info("[传输完成] 文件传输成功: {} -> {}:{} (大小: {} 字节)", localFilePath, server.getHostname(), remoteFilePath, localFile.length());
                return result; // 成功后直接返回
                
            } catch (JSchException e) {
                log.error("[SSH错误] SSH连接失败 (尝试 {}/{} on {}:{} (ID: {})): {}", attempt, MAX_RETRIES, server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                if (attempt == MAX_RETRIES) {
                    log.error("[SSH失败] SSH连接失败 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                    result.setSuccess(false);
                    result.setMessage("SSH连接失败: " + e.getMessage());
                }
            } catch (SftpException e) {
                log.error("[SFTP错误] SFTP传输失败 (尝试 {}/{} on {}:{} (ID: {})): {}", attempt, MAX_RETRIES, server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                if (attempt == MAX_RETRIES) {
                    log.error("[SFTP失败] SFTP传输失败 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                    result.setSuccess(false);
                    result.setMessage("文件传输失败: " + e.getMessage());
                }
            } catch (Exception e) {
                log.error("[传输错误] 文件传输过程中发生错误 (尝试 {}/{} on {}:{} (ID: {})): {}", attempt, MAX_RETRIES, server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                if (attempt == MAX_RETRIES) {
                    log.error("[传输失败] 文件传输过程中发生错误 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                    result.setSuccess(false);
                    result.setMessage("文件传输失败: " + e.getMessage());
                }
            } finally {
                // 关闭连接
                if (channel != null && channel.isConnected()) {
                    try {
                        channel.disconnect();
                        log.debug("[SFTP关闭] 已断开与服务器 {}:{} (ID: {}) 的SFTP通道连接", server.getHostname(), server.getPort(), server.getId());
                    } catch (Exception e) {
                        log.warn("[关闭警告] 关闭SFTP通道时出错 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage());
                    }
                }
                if (session != null && session.isConnected()) {
                    try {
                        session.disconnect();
                        log.info("[会话断开] 已断开与服务器 {}:{} (ID: {}) 的连接", server.getHostname(), server.getPort(), server.getId());
                    } catch (Exception e) {
                        log.warn("[关闭警告] 关闭SSH会话时出错 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage());
                    }
                }
            }
            
            // 如果不是最后一次尝试，等待一段时间再重试
            if (attempt < MAX_RETRIES) {
                try {
                    log.info("[重试等待] 等待 {} 毫秒后进行第 {} 次重试 on {}:{} (ID: {})", RETRY_INTERVAL, attempt + 1, server.getHostname(), server.getPort(), server.getId());
                    Thread.sleep(RETRY_INTERVAL); // 等待指定时间
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    log.warn("[中断] 传输重试等待被中断: {}", ie.getMessage());
                    break;
                }
            }
        }
        
        return result;
    }
    
    /**
     * 从远程服务器下载文件到本地
     * @param server 服务器信息
     * @param remoteFilePath 远程文件路径
     * @param localFilePath 本地文件路径
     * @return 传输结果
     */
    public CommandResult downloadFileFromServer(Server server, String remoteFilePath, String localFilePath) {
        CommandResult result = new CommandResult();
        result.setServerId(server.getId());
        result.setServerName(server.getName());
        
        log.info("[文件下载] 开始从服务器 {}:{} (ID: {}) 下载文件 {} 到本地: {}", server.getHostname(), server.getPort(), server.getId(), remoteFilePath, localFilePath);
        
        // 重试机制
        for (int attempt = 1; attempt <= MAX_RETRIES; attempt++) {
            Session session = null;
            ChannelSftp channel = null;
            
            try {
                // 创建JSch实例
                JSch jsch = new JSch();
                
                // 创建会话
                session = jsch.getSession(server.getUsername(), server.getHostname(), server.getPort());
                
                // 设置密码
                if (server.getPassword() != null && !server.getPassword().isEmpty()) {
                    session.setPassword(server.getPassword());
                }
                
                // 设置SSH配置
                Properties config = new Properties();
                config.put("StrictHostKeyChecking", "no"); // 跳过主机密钥检查
                config.put("PreferredAuthentications", "password,keyboard-interactive,publickey");
                session.setConfig(config);
                
                // 连接
                log.info("[下载连接] 正在连接到服务器 {}:{}", server.getHostname(), server.getPort());
                session.connect(CONNECTION_TIMEOUT); // 使用配置的超时时间
                
                // 创建SFTP通道
                channel = (ChannelSftp) session.openChannel("sftp");
                channel.connect(CHANNEL_TIMEOUT); // 使用配置的超时时间
                
                // 下载文件
                log.info("[下载开始] 开始从 {}:{} 下载文件 {} 到 {}", server.getHostname(), remoteFilePath, localFilePath);
                channel.get(remoteFilePath, localFilePath);
                
                // 获取下载的文件信息
                File downloadedFile = new File(localFilePath);
                result.setSuccess(true);
                result.setMessage("文件下载成功");
                log.info("[下载完成] 文件下载成功: {}:{} -> {} (大小: {} 字节)", server.getHostname(), remoteFilePath, localFilePath, downloadedFile.length());
                return result; // 成功后直接返回
                
            } catch (JSchException e) {
                log.error("[SSH错误] SSH连接失败 (尝试 {}/{} on {}:{} (ID: {})): {}", attempt, MAX_RETRIES, server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                if (attempt == MAX_RETRIES) {
                    log.error("[SSH失败] SSH连接失败 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                    result.setSuccess(false);
                    result.setMessage("SSH连接失败: " + e.getMessage());
                }
            } catch (SftpException e) {
                log.error("[SFTP错误] SFTP下载失败 (尝试 {}/{} on {}:{} (ID: {})): {}", attempt, MAX_RETRIES, server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                if (attempt == MAX_RETRIES) {
                    log.error("[SFTP失败] SFTP下载失败 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                    result.setSuccess(false);
                    result.setMessage("文件下载失败: " + e.getMessage());
                }
            } catch (Exception e) {
                log.error("[下载错误] 文件下载过程中发生错误 (尝试 {}/{} on {}:{} (ID: {})): {}", attempt, MAX_RETRIES, server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                if (attempt == MAX_RETRIES) {
                    log.error("[下载失败] 文件下载过程中发生错误 on {}:{} (ID: {}): {}", server.getHostname(), server.getPort(), server.getId(), e.getMessage(), e);
                    result.setSuccess(false);
                    result.setMessage("文件下载失败: " + e.getMessage());
                }
            } finally {
                // 关闭连接
                if (channel != null && channel.isConnected()) {
                    channel.disconnect();
                    log.debug("[SFTP关闭] 已断开与服务器 {}:{} (ID: {}) 的SFTP通道连接", server.getHostname(), server.getPort(), server.getId());
                }
                if (session != null && session.isConnected()) {
                    session.disconnect();
                    log.info("[会话断开] 已断开与服务器 {}:{} (ID: {}) 的连接", server.getHostname(), server.getPort(), server.getId());
                }
            }
            
            // 如果不是最后一次尝试，等待一段时间再重试
            if (attempt < MAX_RETRIES) {
                try {
                    log.info("[重试等待] 等待 {} 毫秒后进行第 {} 次重试 on {}:{} (ID: {})", RETRY_INTERVAL, attempt + 1, server.getHostname(), server.getPort(), server.getId());
                    Thread.sleep(RETRY_INTERVAL); // 等待指定时间
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    log.warn("[中断] 下载重试等待被中断: {}", ie.getMessage());
                    break;
                }
            }
        }
        
        return result;
    }
    
    /**
     * 获取Linux服务器磁盘信息
     * @param server 服务器信息
     * @return 磁盘信息
     */
    public CommandResult getLinuxDiskInfo(Server server) {
        String command = "lsblk -o NAME,SIZE,TYPE,MOUNTPOINT -J";
        log.debug("[磁盘信息] 获取Linux服务器 {} 磁盘信息", server.getHostname());
        return executeCommand(server, command);
    }
    
    /**
     * 获取Windows服务器磁盘信息
     * @param server 服务器信息
     * @return 磁盘信息
     */
    public CommandResult getWindowsDiskInfo(Server server) {
        String command = "powershell -Command \"Get-WmiObject -Class Win32_LogicalDisk | Select-Object DeviceID, Size, FreeSpace | ConvertTo-Json\"";
        log.debug("[磁盘信息] 获取Windows服务器 {} 磁盘信息", server.getHostname());
        return executeCommand(server, command);
    }
    
    /**
     * 获取Linux服务器目录结构
     * @param server 服务器信息
     * @param path 路径
     * @return 目录结构
     */
    public CommandResult getLinuxDirectoryStructure(Server server, String path) {
        // 使用find命令获取目录结构，限制深度为2级以避免输出过多
        String command = String.format("find %s -maxdepth 2 -type d 2>/dev/null | head -100", path);
        log.debug("[目录结构] 获取Linux服务器 {} 目录结构: {}", server.getHostname(), path);
        return executeCommand(server, command);
    }
    
    /**
     * 获取Windows服务器目录结构
     * @param server 服务器信息
     * @param path 路径
     * @return 目录结构
     */
    public CommandResult getWindowsDirectoryStructure(Server server, String path) {
        // 使用PowerShell获取目录结构，限制深度为2级
        String command = String.format(
            "powershell -Command \"Get-ChildItem -Path '%s' -Directory -Depth 1 | Select-Object FullName | ConvertTo-Json\"", 
            path
        );
        log.debug("[目录结构] 获取Windows服务器 {} 目录结构: {}", server.getHostname(), path);
        return executeCommand(server, command);
    }
    
    /**
     * 检查服务器上是否安装了rclone
     * @param server 服务器信息
     * @return 检查结果
     */
    public CommandResult checkRcloneInstalled(Server server) {
        CommandResult result = new CommandResult();
        result.setServerId(server.getId());
        result.setServerName(server.getName());
        
        try {
            // 更可靠的检查方法
            String checkCommand = "command -v rclone >/dev/null 2>&1 && rclone --version";
            log.info("[rclone检查] 检查服务器 {} 上是否安装了rclone", server.getHostname());
            result = executeCommand(server, checkCommand);
            
            if (result.isSuccess() && result.getOutput() != null && !result.getOutput().trim().isEmpty()) {
                log.info("[rclone状态] 服务器 {} 上已正确安装rclone", server.getHostname());
                result.setMessage("rclone已正确安装");
            } else {
                log.warn("[rclone缺失] 服务器 {} 上未找到可用的rclone", server.getHostname());
                result.setSuccess(false);
                result.setMessage("rclone未安装或不可用");
            }
        } catch (Exception e) {
            log.error("[检查错误] 检查服务器 {} 上rclone时出错: {}", server.getHostname(), e.getMessage(), e);
            result.setSuccess(false);
            result.setMessage("检查rclone时出错: " + e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 连接测试结果类
     */
    public static class ConnectionResult {
        private Long serverId;
        private String serverName;
        private boolean success;
        private String message;
        private String systemInfo;
        
        // Getters and Setters
        public Long getServerId() {
            return serverId;
        }
        
        public void setServerId(Long serverId) {
            this.serverId = serverId;
        }
        
        public String getServerName() {
            return serverName;
        }
        
        public void setServerName(String serverName) {
            this.serverName = serverName;
        }
        
        public boolean isSuccess() {
            return success;
        }
        
        public void setSuccess(boolean success) {
            this.success = success;
        }
        
        public String getMessage() {
            return message;
        }
        
        public void setMessage(String message) {
            this.message = message;
        }
        
        public String getSystemInfo() {
            return systemInfo;
        }
        
        public void setSystemInfo(String systemInfo) {
            this.systemInfo = systemInfo;
        }
    }
    
    /**
     * 命令执行结果类
     */
    public static class CommandResult {
        private Long serverId;
        private String serverName;
        private boolean success;
        private String message;
        private String output;
        
        // Getters and Setters
        public Long getServerId() {
            return serverId;
        }
        
        public void setServerId(Long serverId) {
            this.serverId = serverId;
        }
        
        public String getServerName() {
            return serverName;
        }
        
        public void setServerName(String serverName) {
            this.serverName = serverName;
        }
        
        public boolean isSuccess() {
            return success;
        }
        
        public void setSuccess(boolean success) {
            this.success = success;
        }
        
        public String getMessage() {
            return message;
        }
        
        public void setMessage(String message) {
            this.message = message;
        }
        
        public String getOutput() {
            return output;
        }
        
        public void setOutput(String output) {
            this.output = output;
        }
    }
}